﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics;

namespace LasRendering
{
    public class LasRenderingWindow : GameWindow
    {
        private const string WINDOW_TITLE = @"LAS Rendering";

        private static TimeSpan fpsUpdateInterval;
        private static int displayCount;
        private static DateTime t0;

        private static int totalVertexCount;
        private static int renderingVertexCount;

        public LasRenderingWindow()
            : base(
            Convert.ToInt32(ConfigurationManager.AppSettings["windowWidth"]),
            Convert.ToInt32(ConfigurationManager.AppSettings["windowHeight"]),
            GraphicsMode.Default,
            WINDOW_TITLE)
        {
            this.VSync = (VSyncMode)Enum.Parse(typeof(VSyncMode), ConfigurationManager.AppSettings["vSyncMode"], true);
            this.WindowBorder = WindowBorder.Fixed;

            //Read settings from app.config
            fpsUpdateInterval = TimeSpan.FromSeconds(Convert.ToSingle(ConfigurationManager.AppSettings["fpsUpdateInterval"]));
        }

        protected override void OnLoad(EventArgs e)
        {
            VertexHelper.Init();
            var vertexQuadTree = VertexHelper.Preprocess();
            totalVertexCount = vertexQuadTree.Count;
            Graphics.Init(this.Width, this.Height, vertexQuadTree);
        }

        protected override void OnUnload(EventArgs e)
        {
            Graphics.Uninit();
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            Graphics.RenderFrame(this.Width, this.Height, out renderingVertexCount);
            SwapBuffers();
            displayCount++;
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            if (this.Keyboard[Key.Escape])
            {
                this.Exit();
                return;
            }

            if (Graphics.AnimationEnabled)
            {
                Graphics.CameraRotationY += 0.003f;
            }

            UpdateFpsDisplayIfNecessary();
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            switch (e.KeyChar)
            {
                case ' ': // space
                    Graphics.AnimationEnabled = !Graphics.AnimationEnabled;
                    break;
                case 'f':
                    Graphics.CameraHeight *= 1.05f;
                    break;
                case 'v':
                    Graphics.CameraHeight /= 1.05f;
                    break;
                case 'a':
                    Graphics.CameraRotationY -= 0.01f;
                    break;
                case 'd':
                    Graphics.CameraRotationY += 0.01f;
                    break;
                case 'w':
                    Graphics.CameraDistance /= 1.05f;
                    break;
                case 's':
                    Graphics.CameraDistance *= 1.05f;
                    break;
                case 'z':
                    Graphics.DetailsLevel--;
                    break;
                case 'x':
                    Graphics.DetailsLevel++;
                    break;
                case 'c':
                    Graphics.TwoPassesEnabled = !Graphics.TwoPassesEnabled;
                    break;
                case 'g':
                    Graphics.FovY *= 1.05f;
                    break;
                case 'b':
                    Graphics.FovY /= 1.05f;
                    break;
                case 'i':
                    Graphics.CenterPosition = new Vector3(Graphics.CenterPosition.X + 10, Graphics.CenterPosition.Y, Graphics.CenterPosition.Z);
                    break;
                case 'k':
                    Graphics.CenterPosition = new Vector3(Graphics.CenterPosition.X - 10, Graphics.CenterPosition.Y, Graphics.CenterPosition.Z);
                    break;
                case 'j':
                    Graphics.CenterPosition = new Vector3(Graphics.CenterPosition.X, Graphics.CenterPosition.Y, Graphics.CenterPosition.Z - 10);
                    break;
                case 'l':
                    Graphics.CenterPosition = new Vector3(Graphics.CenterPosition.X, Graphics.CenterPosition.Y, Graphics.CenterPosition.Z + 10);
                    break;
/*
                case 't':
                    Graphics.CameraHeight = 2127.9043f;
                    Graphics.CameraRotationY = -0.3f;
                    Graphics.CameraDistance = 2551.22437f;
                    break;
 */
                default:
                    break;
            }
        }

        private void UpdateFpsDisplayIfNecessary()
        {
            DateTime t = DateTime.Now;
            TimeSpan delta = t - t0;
            if (delta > fpsUpdateInterval)
            {
                t0 = t;
                this.Title = string.Format("{0} ({1}/{2} points) (fps {3:f1})", 
                    WINDOW_TITLE, 
                    renderingVertexCount,
                    totalVertexCount, 
                    displayCount / delta.TotalSeconds);
                displayCount = 0;
            }
        }

    }
}
